{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.path.append(r'D:\\codeproject\\data-process')\n",
    "from tqdm.notebook import tqdm\n",
    "\n",
    "# 确保 pandas 的 apply 方法可以与 tqdm 一起使用\n",
    "\n",
    "import os\n",
    "import pandas as pd\n",
    "tqdm.pandas()\n",
    "import numpy as np\n",
    "import re\n",
    "from datetime import datetime, timedelta\n",
    "from data_deal.function import get_stage_hr, get_stage_rr,rpe_get\n",
    "from data_deal.merger import ecg_deal, singlework_deal,rrdata_deal\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "rrdatapath='D:\\\\学习&科研\\\\华为手表项目\\\\华为数据\\\\规律跑者数据样例\\\\long_term_deal\\\\polar\\\\1016\\\\rrdata'\n",
    "datapath = 'D:\\\\学习&科研\\\\华为手表项目\\\\华为数据\\\\规律跑者数据样例\\\\long_term_deal\\\\polar\\\\1016\\\\data'\n",
    "singleworkpath = 'D:\\\\学习&科研\\\\华为手表项目\\\\华为数据\\\\规律跑者数据样例\\\\long_term_deal\\\\huawei-workouts\\\\1016-singleworkouts.csv'\n",
    "healthpath='D:\\\\学习&科研\\\\华为手表项目\\\\华为数据\\\\规律跑者数据样例\\\\long_term_deal\\\\healthtest\\\\1016-coros-healthtest.csv'\n",
    "# 获取 datapath 路径下的所有文件列表\n",
    "#读取相关文件\n",
    "health_df = pd.read_csv(healthpath)\n",
    "health_df['datetime']=health_df['timestamp'].apply(lambda x: datetime.fromtimestamp(x))\n",
    "\n",
    "datafiles = os.listdir(datapath)\n",
    "rrdatafiles=os.listdir(rrdatapath)\n",
    "singlework_df = singlework_deal(singleworkpath)\n",
    "# 确保 singlework_df 的时间列是 pandas datetime 类型\n",
    "singlework_df['活动.测量开始时间'] = pd.to_datetime(singlework_df['活动.测量开始时间'])\n",
    "singlework_df['活动.测量结束时间'] = pd.to_datetime(singlework_df['活动.测量结束时间'])\n",
    "\n",
    "# 按照文件名区分\n",
    "file_df = pd.DataFrame(datafiles, columns=['data_filename'])\n",
    "file_df['rrdata_filename']=rrdatafiles\n",
    "file_df['test'] = file_df['rrdata_filename'].apply(lambda x: os.path.splitext(x)[0])\n",
    "file_df[['test_id', 'day', 'state']] = file_df['rrdata_filename'].apply(lambda x: os.path.splitext(x)[0]).str.split('-', expand=True)\n",
    "file_df['data_file_path'] = file_df['data_filename'].apply(lambda x: os.path.join(datapath, x))\n",
    "file_df['rrdata_file_path'] = file_df['rrdata_filename'].apply(lambda x: os.path.join(rrdatapath, x))\n",
    "file_df = file_df[file_df['state'] != 'not running']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_activity_times(file_path):\n",
    "        try:\n",
    "            # 读取 CSV 文件\n",
    "            # df = ecg_deal(file_path)  # 需要你定义这个处理函数\n",
    "            df=rrdata_deal(file_path)\n",
    "\n",
    "            # 提取第一行和最后一行的 ecg_timestamp\n",
    "            start_time = df.iloc[0]['timestamp']\n",
    "            end_time = df.iloc[-1]['timestamp']\n",
    "            \n",
    "            start_time = int(start_time)  # 或者 float(start_time)，取决于你的数据类型\n",
    "            end_time = int(end_time)      # 或者 float(end_time)，取决于你的数据类型\n",
    "\n",
    "            start_time = pd.to_datetime(start_time, unit='ms')\n",
    "            end_time = pd.to_datetime(end_time, unit='ms')\n",
    "            start_time = start_time + timedelta(hours=8)\n",
    "            end_time = end_time + timedelta(hours=8)\n",
    "            return start_time, end_time\n",
    "        except Exception as e:\n",
    "            print(f\"Error processing file {file_path}: {e}\")\n",
    "            return None, None\n",
    "   \n",
    "    # 获取活动开始时间和结束时间，并添加到 DataFrame 中\n",
    "\n",
    "file_df[['polar采集开始', 'polar采集结束']] = file_df['rrdata_file_path'].apply(get_activity_times).apply(pd.Series)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b9fa246ede744d678632ed76b2778112",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "跑步开始时间和结束时间:   0%|          | 0/68 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "\n",
    "def match_running_times(row):\n",
    "    file_start = row['polar采集开始']\n",
    "    \n",
    "    for _, single_row in singlework_df.iterrows():\n",
    "        measure_start = single_row['活动.测量开始时间']\n",
    "        measure_end = single_row['活动.测量结束时间']\n",
    "       \n",
    "        # 计算时间差\n",
    "        time_diff = abs((measure_start - file_start).total_seconds())\n",
    "        \n",
    "        # 如果时间差在30分钟以内，则返回测量的开始和结束时间\n",
    "        if time_diff <= 30 * 60:\n",
    "            return pd.Series([measure_start, measure_end])\n",
    "    \n",
    "    # 如果没有匹配的时间段，返回 None\n",
    "    return pd.Series([None, None])\n",
    "\n",
    "# 应用函数并将结果存入新的列\n",
    "tqdm.pandas(desc='跑步开始时间和结束时间')\n",
    "file_df[['跑步开始时间', '跑步结束时间']] = file_df.progress_apply(match_running_times, axis=1)\n",
    "#再增加两列kuaice-HR、kuaice-HRV，循环file_df中state非running的行的活动开始时间，与health_df['datetime']匹配，时间差不超过10分钟，匹配到就把health_df的HR\tHRV，存入kuaice-HR、kuaice-HRV\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5bce5e7343d9406b98e13f55e454d7ab",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "匹配healthtest:   0%|          | 0/68 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# 定义匹配 health_df 中 HR 和 HRV 的函数\n",
    "def match_kuaice_times(row):\n",
    "    if row['state'] != 'running':\n",
    "        file_start = row['polar采集开始']\n",
    "        for _, kuaice_row in health_df.iterrows():\n",
    "            kuaice_time = kuaice_row['datetime']\n",
    "            time_diff = abs((kuaice_time - file_start).total_seconds())\n",
    "            if time_diff <= 10 * 60:\n",
    "                return pd.Series([kuaice_row['HR'], kuaice_row['HRV']])\n",
    "    return pd.Series([None, None])\n",
    "\n",
    "# 应用函数并将结果存入新的列\n",
    "tqdm.pandas(desc='匹配healthtest')\n",
    "file_df[['healthtest-HR', 'healthtest-HRV']] = file_df.progress_apply(match_kuaice_times, axis=1)\n",
    "file_df['healthtest-type']=healthpath.split('\\\\')[-1].split('-')[1]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "running_df = file_df.loc[file_df['state'] == 'running']\n",
    "\n",
    "# 复制为三行，并修改 state 值\n",
    "running_df_1 = running_df.copy()\n",
    "running_df_1['state'] = 'rest_before_running'\n",
    "\n",
    "running_df_2 = running_df.copy()\n",
    "running_df_2['state'] = 'running_running'\n",
    "\n",
    "running_df_3 = running_df.copy()\n",
    "running_df_3['state'] = 'rest_after_running'\n",
    "\n",
    "# 合并生成的三份数据\n",
    "result_df = pd.concat([running_df_1, running_df_2, running_df_3], ignore_index=True)\n",
    "\n",
    "# 删除原始数据中 state 为 'running' 的行\n",
    "file_df = file_df[file_df['state'] != 'running']\n",
    "\n",
    "# 将生成的数据合并回原始 DataFrame\n",
    "file_df = pd.concat([file_df, result_df], ignore_index=True)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d6b55cf30ba7493889eb2a95fa00ca63",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "全程rr,hr:   0%|          | 0/96 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def get_activity_rr(row):\n",
    "    try:\n",
    "        file_path = row['rrdata_file_path']\n",
    "        df = rrdata_deal(file_path)\n",
    "        df['timestamp'] = df['timestamp'].astype('int64')\n",
    "\n",
    "        rr_list, hr_list = [], []\n",
    "\n",
    "        if row['state'] == 'morning' or row['state'] == 'evening':\n",
    "            rr_list = df['rr'].to_list()\n",
    "            hr_list = pd.to_numeric(df['HR'], errors='coerce').tolist()\n",
    "\n",
    "        elif row['state'] == 'rest_before_running':\n",
    "            starttime = int(pd.to_datetime(row['polar采集开始']).tz_localize('Asia/Shanghai').timestamp() * 1000)\n",
    "            endtime = int(pd.to_datetime(row['跑步开始时间']).tz_localize('Asia/Shanghai').timestamp() * 1000)\n",
    "            get_df = df[(df['timestamp'] >= starttime) & (df['timestamp'] <= endtime)]\n",
    "            rr_list = get_df['rr'].to_list()\n",
    "            hr_list = pd.to_numeric(get_df['HR'], errors='coerce').tolist()\n",
    "\n",
    "        elif row['state'] == 'running_running':\n",
    "            starttime = int(pd.to_datetime(row['跑步开始时间']).tz_localize('Asia/Shanghai').timestamp() * 1000)\n",
    "            endtime = int(pd.to_datetime(row['跑步结束时间']).tz_localize('Asia/Shanghai').timestamp() * 1000)\n",
    "            get_df = df[(df['timestamp'] >= starttime) & (df['timestamp'] <= endtime)]\n",
    "            rr_list = get_df['rr'].to_list()\n",
    "            hr_list = pd.to_numeric(get_df['HR'], errors='coerce').tolist()\n",
    "\n",
    "        elif row['state'] == 'rest_after_running':\n",
    "            starttime = int(pd.to_datetime(row['跑步结束时间']).tz_localize('Asia/Shanghai').timestamp() * 1000)\n",
    "            endtime = int(pd.to_datetime(row['polar采集结束']).tz_localize('Asia/Shanghai').timestamp() * 1000)\n",
    "            get_df = df[(df['timestamp'] >= starttime) & (df['timestamp'] <= endtime)]\n",
    "            rr_list = get_df['rr'].to_list()\n",
    "            hr_list = pd.to_numeric(get_df['HR'], errors='coerce').tolist()\n",
    "\n",
    "        # 扁平化 rr_list（如果它包含子列表）\n",
    "        flattened_rr_list = [int(item) for sublist in rr_list for item in sublist if item and item.strip().isdigit()]\n",
    "\n",
    "        # 返回两个列表作为 pd.Series\n",
    "        return pd.Series([flattened_rr_list, hr_list])\n",
    "\n",
    "    except Exception as e:\n",
    "        print(f\"rr error {file_path}: {e}\")\n",
    "        return pd.Series([[], []])  # 如果发生错误，返回空列表\n",
    "\n",
    "tqdm.pandas(desc='全程rr,hr')\n",
    "file_df[['全程rr', '全程hr']] = file_df.progress_apply(get_activity_rr, axis=1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c9519da9df574ebebdc5fff84a60e98c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "rpe:   0%|          | 0/96 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#按照时间节点，分别找出rr和hr，及rpe的范围，1静息的全程，2跑步前静息、3跑步全程、4跑后静息\n",
    "# 打印结果\n",
    "# print(file_df[['filename','活动开始时间', '活动结束时间', '跑步开始时间', '跑步结束时间']])\n",
    "#按照polar采集开始排序\n",
    "file_df = file_df.sort_values(by='polar采集开始')\n",
    "\n",
    "\n",
    "def get_rpe(row):\n",
    "    rpelist=rpe_get(row['data_file_path'])\n",
    "    \n",
    "    return pd.Series(rpelist)\n",
    "\n",
    "tqdm.pandas(desc='rpe')\n",
    "file_df[['psychology_RPE','physiology_RPE','now_RPE','train_RPE']]=file_df.progress_apply(get_rpe,axis=1)\n",
    "\n",
    "\n",
    "#找到ecgdata中对应的 rpe，按照不同情况填入file中"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "#polar_rr为列表数据，通过函数计算得到指标，加入该行\n",
    "#polar_rr为列表数据，通过函数计算得到指标，加入该行\n",
    "# 定义 calculate_sd1_sd2 函数\n",
    "import pyhrv.nonlinear as nl  # 导入pyHRV的非线性分析模块\n",
    "all_stages_df=file_df\n",
    "all_stages_df['全程rr'] = all_stages_df['全程rr'].apply(lambda x: eval(x) if isinstance(x, str) else x)\n",
    "\n",
    "# 定义 calculate_sd1_sd2 函数\n",
    "def calculate_sd1_sd2(rr_intervals):\n",
    "    if not isinstance(rr_intervals, (list, np.ndarray)) or len(rr_intervals) < 2:\n",
    "        return np.nan, np.nan  # 如果数据不符合要求，返回 NaN\n",
    "    \n",
    "    rr_diff = np.diff(rr_intervals)\n",
    "    rr_diff_n = rr_diff[:-1]\n",
    "    rr_diff_np1 = rr_diff[1:]\n",
    "\n",
    "    SD1 = np.sqrt(np.std(rr_diff_n - rr_diff_np1, ddof=1) / 2)\n",
    "    SD2 = np.sqrt(np.std(rr_diff_n + rr_diff_np1, ddof=1) / 2)\n",
    "\n",
    "    return SD1, SD2\n",
    "def calculate_sdnn_rmssd(rr_intervals):\n",
    "    SDNN = np.std(rr_intervals, ddof=1)  # SDNN的计算\n",
    "    RMSSD = np.sqrt(np.mean(np.square(np.diff(rr_intervals))))  # RMSSD的计算\n",
    "    return SDNN, RMSSD\n",
    "def calculate_cv(rr_intervals):\n",
    "    mean_rr = np.mean(rr_intervals)\n",
    "    std_rr = np.std(rr_intervals, ddof=1)\n",
    "    cv = std_rr / mean_rr if mean_rr != 0 else 0\n",
    "    mean_hr = 60000 / mean_rr\n",
    "    return cv, mean_hr\n",
    "\n",
    "def calculate_dfa(rr_intervals):\n",
    "    # 使用pyHRV计算DFA\n",
    "    dfa_result = nl.dfa(rr_intervals ,show=False)\n",
    "    alpha1 = dfa_result['dfa_alpha1']  # DFA的短期指数\n",
    "    alpha2 = dfa_result['dfa_alpha2']  # DFA的长期指数\n",
    "    return alpha1, alpha2\n",
    "# 应用 calculate_sd1_sd2 函数并提取 SD1 和 SD2\n",
    "all_stages_df[['SD1', 'SD2']] = all_stages_df['全程rr'].apply(lambda x: pd.Series(calculate_sd1_sd2(x)))\n",
    "\n",
    "all_stages_df[['SDNN', 'RMSSD']] = all_stages_df['全程rr'].apply(lambda x: pd.Series(calculate_sdnn_rmssd(x)))\n",
    "all_stages_df[['CV', 'Mean_HR']] = all_stages_df['全程rr'].apply(lambda x: pd.Series(calculate_cv(x)))\n",
    "# all_stages_df[['alpha1', 'alpha2']] = all_stages_df['全程rr'].apply(lambda x: pd.Series(calculate_dfa(x)))\n",
    "#指定某几列数据为数字类型\n",
    "# all_stages_df[['SD1', 'SD2','SDNN', 'RMSSD','CV', 'Mean_HR','alpha1', 'alpha2']] = all_stages_df[['SD1', 'SD2','SDNN', 'RMSSD','CV', 'Mean_HR','alpha1', 'alpha2']].astype(float)  # 或 int\n",
    "all_stages_df[['SD1', 'SD2','SDNN', 'RMSSD','CV', 'Mean_HR']] = all_stages_df[['SD1', 'SD2','SDNN', 'RMSSD','CV', 'Mean_HR']].astype(float)  # 或 int\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "#删除state=not running的数据\n",
    "\n",
    "all_stages_df.to_csv('D:\\\\学习&科研\\\\华为手表项目\\\\华为数据\\\\规律跑者数据样例\\\\long_term_deal\\\\polar\\\\1016\\\\allstage_df.csv', index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MLandDL",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
